home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 11 / Mac Magazin and MacEasy Magazine CD - Issue 11.iso / Sharewarebibliothek / Entwickler / WASTE 1.1b1 Distribution / Demo Source / WEDemoMenus.p < prev    next >
Text File  |  1995-06-01  |  23KB  |  956 lines

  1. unit WEDemoMenus;
  2.  
  3. { WASTE DEMO PROJECT: }
  4. { Menu Handling }
  5.  
  6. { Copyright © 1993-1995 Marco Piovanelli }
  7. { All Rights Reserved }
  8.  
  9. interface
  10.     uses
  11.         WEDemoIntf;
  12.  
  13.     function InitializeMenus: OSErr;
  14.     procedure PrepareMenus;
  15.     procedure DoMenuChoice (menuChoice: LongInt);
  16.     function DoClose (closing: ClosingOption;
  17.                                     saving: SavingOption;
  18.                                     window: WindowPtr): OSErr;
  19.     function DoQuit (saving: SavingOption): OSErr;
  20.  
  21. implementation
  22.     uses
  23.         Aliases, Devices, LowMem, StandardFile, ToolUtils, WEDemoAbout, WEDemoFiles, WEDemoWindows, DialogUtils, WETabs;
  24.  
  25.     const
  26.  
  27. { resource types }
  28.  
  29.         kTypeMenuColorTable = 'mctb';
  30.  
  31.     var
  32.  
  33.         sColors: Handle;            { handle to the 'mctb' resource for the Color menu }
  34.  
  35.     function MySFDialogFilter (dialog: DialogPtr;
  36.                                     var event: EventRecord;
  37.                                     var item: Integer;
  38.                                     yourData: Ptr): Boolean;
  39.     begin
  40.         MySFDialogFilter := CallModalFilterProc(dialog, event, item, GetMyStandardDialogFilter);
  41.     end;  { MySFDialogFilter }
  42.  
  43.     var
  44.  
  45. { static variable for exclusive use by GetMySFDialogFilter }
  46.  
  47.         sMySFDialogFilter: ModalFilterYDUPP;
  48.  
  49.     function GetMySFDialogFilter: ModalFilterYDUpp;
  50.     begin
  51.         if (sMySFDialogFilter = nil) then
  52.             sMySFDialogFilter := NewModalFilterYDProc(@MySFDialogFilter);
  53.         GetMySFDialogFilter := sMySFDialogFilter;
  54.     end;  { GetMySFDialogFilter }
  55.  
  56.     procedure SetDefaultDirectory (vRefNum: Integer;
  57.                                     dirID: LongInt);
  58.     begin
  59.         LMSetCurDirStore(dirID);
  60.         LMSetSFSaveDisk(-vRefNum);
  61.     end;  { SetDefaultDirectory }
  62.  
  63.     function FindMenuItemText (menu: MenuRef;
  64.                                     stringToFind: Str255): Integer;
  65.         var
  66.             item: Integer;
  67.             itemText: Str255;
  68.     begin
  69.         for item := CountMItems(menu) downto 1 do
  70.             begin
  71.                 GetMenuItemText(menu, item, itemText);
  72.                 if EqualString(itemText, stringToFind, false, false) then
  73.                     Leave;
  74.             end;
  75.         FindMenuItemText := item;
  76.     end;  { FindMenuItemText }
  77.  
  78.     function EqualColor (var rgb1, rgb2: RGBColor): Boolean;
  79.     begin
  80.         EqualColor := (rgb1.red = rgb2.red) and (rgb1.green = rgb2.green) and (rgb1.blue = rgb2.blue);
  81.     end;  { EqualColor }
  82.  
  83.     procedure PrepareMenus;
  84.         var
  85.             window: WindowPtr;
  86.             hWE: WEHandle;
  87.             menu: MenuRef;
  88.             item: Integer;
  89.             itemText: Str255;
  90.             selStart, selEnd: LongInt;
  91.             actionKind: WEActionKind;
  92.             mode: Integer;
  93.             ts: TextStyle;
  94.             temp: Boolean;
  95.     begin
  96.  
  97. { get a pointer to the frontmost window, if any }
  98.         window := FrontWindow;
  99.  
  100. { get associated WE instance }
  101.         hWE := DocumentPeek(window)^.hWE;
  102.  
  103. { *** FILE MENU *** }
  104.         menu := GetMenuHandle(kMenuFile);
  105.  
  106. { first disable all items }
  107.         for item := CountMItems(menu) downto 1 do
  108.             DisableItem(menu, item);
  109.  
  110. { New, Open and Quit are always enabled }
  111.         EnableItem(menu, kItemNew);
  112.         EnableItem(menu, kItemOpen);
  113.         EnableItem(menu, kItemQuit);
  114.  
  115. { enable Close and Save As if there is an active window }
  116.         if (window <> nil) then
  117.             begin
  118.                 EnableItem(menu, kItemClose);
  119.                 EnableItem(menu, kItemSaveAs);
  120.  
  121. { enable Save if the active window is dirty }
  122.                 if (WEGetModCount(hWE) > 0) then
  123.                     EnableItem(menu, kItemSave);
  124.             end;
  125.  
  126. { *** EDIT MENU *** }
  127.         menu := GetMenuHandle(kMenuEdit);
  128.  
  129. { first disable all items }
  130.         for item := CountMItems(menu) downto 1 do
  131.             DisableItem(menu, item);
  132.  
  133. { by default, the Undo menu item should read "Can't Undo" }
  134.         GetIndString(itemText, kUndoStringsID, 1);
  135.         SetMenuItemText(menu, kItemUndo, itemText);
  136.  
  137.         if (window <> nil) then
  138.             begin
  139.  
  140. { enable Paste if there's anything pasteable on the Clipboard }
  141.                 if (WECanPaste(hWE)) then
  142.                     EnableItem(menu, kItemPaste);
  143.  
  144. { enable Undo if anything can be undone }
  145.                 actionKind := WEGetUndoInfo(temp, hWE);
  146.                 if (actionKind <> weAKNone) then
  147.                     begin
  148.                         EnableItem(menu, kItemUndo);
  149.  
  150. { change the Undo menu item to "Undo"/"Redo" + name of action to undo }
  151.                         GetIndString(itemText, kUndoStringsID, 2 * actionKind + ORD(temp));
  152.                         SetMenuItemText(menu, kItemUndo, itemText);
  153.                     end;
  154.  
  155. { enable Select All if there is anything to select }
  156.                 if (WEGetTextLength(hWE) > 0) then
  157.                     EnableItem(menu, kItemSelectAll);
  158.  
  159. { get the current selection range }
  160.                 WEGetSelection(selStart, selEnd, hWE);
  161.                 if (selStart <> selEnd) then
  162.                     begin
  163.  
  164. { enable Cut, Copy and Clear if the selection range is not empty }
  165.                         EnableItem(menu, kItemCut);
  166.                         EnableItem(menu, kItemCopy);
  167.                         EnableItem(menu, kItemClear);
  168.                     end;
  169.  
  170. { determine which style attributes are continuous over the current selection range }
  171. { we'll need this information in order to check the Font/Size/Style/Color menus properly }
  172.                 mode := weDoAll;        { query about all attributes }
  173.                 temp := WEContinuousStyle(mode, ts, hWE);
  174.             end
  175.         else
  176.             mode := 0;        { no window; so check no item }
  177.  
  178. { *** FONT MENU *** }
  179.         menu := GetMenuHandle(kMenuFont);
  180.  
  181. { first remove all check marks }
  182.         for item := CountMItems(menu) downto 1 do
  183.             CheckItem(menu, item, false);
  184.  
  185. { if there is a continuous font all over the selection range, }
  186. { check the corresponding menu item }
  187.         if (BAND(mode, weDoFont) <> 0) then
  188.             begin
  189.                 GetFontName(ts.tsFont, itemText);
  190.                 CheckItem(menu, FindMenuItemText(menu, itemText), true);
  191.             end;
  192.  
  193. { *** SIZE MENU *** }
  194.         menu := GetMenuHandle(kMenuSize);
  195.  
  196. { first remove all check marks }
  197.         for item := CountMItems(menu) downto 1 do
  198.             CheckItem(menu, item, false);
  199.  
  200. { if there is a continuous font size all over the selection range, }
  201. { check the corresponding menu item }
  202.         if (BAND(mode, weDoSize) <> 0) then
  203.             begin
  204.                 NumToString(ts.tsSize, itemText);
  205.                 CheckItem(menu, FindMenuItemText(menu, itemText), true);
  206.             end;
  207.  
  208. { *** STYLE MENU *** }
  209.         menu := GetMenuHandle(kMenuStyle);
  210.  
  211. { first remove all check marks }
  212.         for item := CountMItems(menu) downto 1 do
  213.             CheckItem(menu, item, false);
  214.  
  215. { check the Style menu items corresponding to style attributes }
  216. { which are continuous over the current selection range }
  217.         if (BAND(mode, weDoFace) <> 0) then
  218.             begin
  219.  
  220.                 if (ts.tsFace = []) then
  221.                     CheckItem(menu, kItemPlainText, true);
  222.  
  223.                 if (bold in ts.tsFace) then
  224.                     CheckItem(menu, kItemBold, true);
  225.  
  226.                 if (italic in ts.tsFace) then
  227.                     CheckItem(menu, kItemItalic, true);
  228.  
  229.                 if (underline in ts.tsFace) then
  230.                     CheckItem(menu, kItemUnderline, true);
  231.  
  232.                 if (outline in ts.tsFace) then
  233.                     CheckItem(menu, kItemOutline, true);
  234.  
  235.                 if (shadow in ts.tsFace) then
  236.                     CheckItem(menu, kItemShadow, true);
  237.  
  238.                 if (condense in ts.tsFace) then
  239.                     CheckItem(menu, kItemCondensed, true);
  240.  
  241.                 if (extend in ts.tsFace) then
  242.                     CheckItem(menu, kItemExtended, true);
  243.  
  244.             end;
  245.  
  246. { *** COLOR MENU *** }
  247.         menu := GetMenuHandle(kMenuColor);
  248.  
  249. { first remove all check marks }
  250.         for item := CountMItems(menu) downto 1 do
  251.             CheckItem(menu, item, false);
  252.  
  253. { if there is a continuous color all over the selection range, }
  254. { check the corresponding menu item (if any) }
  255.         if (BAND(mode, weDoColor) <> 0) then
  256.             with MenuCRsrcHandle(sColors)^^ do
  257.                 for item := numEntries - 1 downto 0 do
  258.                     if (EqualColor(ts.tsColor, mcEntryRecs[item].mctRGB2)) then
  259.                         CheckItem(menu, mcEntryRecs[item].mctItem, true);
  260.  
  261. { *** FEATURES MENU *** }
  262.         menu := GetMenuHandle(kMenuFeatures);
  263.  
  264. { first remove all check marks (except the first item, which has a submenu!!) }
  265.         for item := CountMItems(menu) downto 2 do
  266.             CheckItem(menu, item, false);
  267.  
  268.         if (window <> nil) then
  269.             begin
  270.  
  271. { mark each item according to the corresponding feature }
  272.                 if (WEIsTabHooks(hWE)) then
  273.                     begin
  274.                         CheckItem(menu, kItemTabHooks, true);
  275.                         DisableItem(menu, kItemAlignment);
  276.                     end
  277.                 else
  278.                     EnableItem(menu, kItemAlignment);
  279.  
  280.                 if Boolean(WEFeatureFlag(weFAutoScroll, weBitTest, hWE)) then
  281.                     CheckItem(menu, kItemAutoScroll, true);
  282.  
  283.                 if Boolean(WEFeatureFlag(weFOutlineHilite, weBitTest, hWE)) then
  284.                     CheckItem(menu, kItemOutlineHilite, true);
  285.  
  286.                 if Boolean(WEFeatureFlag(weFReadOnly, weBitTest, hWE)) then
  287.                     CheckItem(menu, kItemReadOnly, true);
  288.  
  289.                 if Boolean(WEFeatureFlag(weFIntCutAndPaste, weBitTest, hWE)) then
  290.                     CheckItem(menu, kItemIntCutAndPaste, true);
  291.  
  292.                 if Boolean(WEFeatureFlag(weFDragAndDrop, weBitTest, hWE)) then
  293.                     CheckItem(menu, kItemDragAndDrop, true);
  294.  
  295.                 if Boolean(WEFeatureFlag(weFDrawOffscreen, weBitTest, hWE)) then
  296.                     CheckItem(menu, kItemOffscreenDrawing, true);
  297.  
  298.             end;
  299.  
  300. { *** ALIGNMENT MENU *** }
  301.         menu := GetMenuHandle(kMenuAlignment);
  302.  
  303. { first remove all check marks }
  304.         for item := CountMItems(menu) downto 1 do
  305.             CheckItem(menu, item, false);
  306.  
  307.         if (window <> nil) then
  308.             begin
  309.  
  310. { find the Alignment menu item corresponding to the current alignment style }
  311.                 case WEGetAlignment(hWE) of
  312.  
  313.                     weFlushLeft: 
  314.                         item := kItemAlignLeft;
  315.  
  316.                     weFlushRight: 
  317.                         item := kItemAlignRight;
  318.  
  319.                     weFlushDefault: 
  320.                         item := kItemAlignDefault;
  321.  
  322.                     weCenter: 
  323.                         item := kItemCenter;
  324.  
  325.                     weJustify: 
  326.                         item := kItemJustify;
  327.  
  328.                     otherwise
  329.                         ;
  330.                 end;  { case }
  331.  
  332. { check the menu item }
  333.                 CheckItem(menu, item, true);
  334.             end;
  335.     end;  { PrepareMenus }
  336.  
  337.     procedure DoDeskAcc (menuItem: Integer);
  338.         var
  339.             daName: Str255;
  340.             daNumber: Integer;
  341.     begin
  342.         GetMenuItemText(GetMenuHandle(kMenuApple), menuItem, daName);
  343.         daNumber := OpenDeskAcc(daName);
  344.     end;  { DoDeskAcc }
  345.  
  346.     function DoNew: OSErr;
  347.     begin
  348.  
  349. { create a new window from scratch }
  350.         DoNew := CreateWindow(nil);
  351.     end;  { DoNew }
  352.  
  353.     function DoOpen: OSErr;
  354.         var
  355.             reply: StandardFileReply;
  356.             typeList: SFTypeList;
  357.     begin
  358.         DoOpen := noErr;
  359.  
  360. { set up a list of file types we can open for StandardGetFile }
  361.         typeList[0] := kTypeText;
  362.  
  363. { put up the standard Open dialog box }
  364. { (we use CustomGetFile instead of StandardGetFile because we want to provide }
  365. { our own dialog filter procedure that takes care of updating our windows) }
  366.         CustomGetFile(nil, 1, typeList, reply, 0, Point(-1), nil, GetMySFDialogFilter, nil, nil, nil);
  367.  
  368. { if the user okayed the dialog, create a new window from the specified file }
  369.         if (reply.sfGood) then
  370.             DoOpen := CreateWindow(@reply.sfFile)
  371.         else
  372.             DoOpen := userCanceledErr;
  373.  
  374.     end;  { DoOpen }
  375.  
  376.     function SaveWindow (pFileSpec: FSSpecPtr;
  377.                                     window: WindowPtr): OSErr;
  378.         var
  379.             err: OSErr;
  380.     begin
  381.         ForgetHandle(DocumentPeek(window)^.fileAlias);
  382.  
  383. { save the text }
  384.         err := WriteTextFile(pFileSpec, DocumentPeek(window)^.hWE);
  385.         if (err = noErr) then
  386.             begin
  387.  
  388. { set the window title to the file name }
  389.                 SetWTitle(window, pFileSpec^.name);
  390.  
  391. { replace the old window alias (if any) with a new one created from pFileSpec }
  392.                 ForgetHandle(DocumentPeek(window)^.fileAlias);
  393.                 err := NewAlias(nil, pFileSpec^, AliasHandle(DocumentPeek(window)^.fileAlias));
  394.             end;
  395.  
  396.         SaveWindow := err;
  397.  
  398.     end;  { SaveWindow }
  399.  
  400.     function DoSaveAs (suggestedTarget: FSSpecPtr;
  401.                                     window: WindowPtr): OSErr;
  402.         var
  403.             hPrompt: StringHandle;
  404.             defaultName: Str255;
  405.             reply: StandardFileReply;
  406.     begin
  407.  
  408. { get the prompt string for CustomPutFile from a 'STR ' resource and lock it }
  409.         hPrompt := GetString(kPromptStringID);
  410.         HLockHi(Handle(hPrompt));
  411.  
  412. { if a suggested target file is provided, use its name as the default name }
  413.         if (suggestedTarget <> nil) then
  414.             begin
  415.                 defaultName := suggestedTarget^.name;
  416.                 SetDefaultDirectory(suggestedTarget^.vRefNum, suggestedTarget^.parID);
  417.             end
  418.         else
  419.  
  420. { otherwise use the window title as default name for CustomPutFile }
  421.             GetWTitle(window, defaultName);
  422.  
  423. { put up the standard Save dialog box }
  424.         CustomPutFile(hPrompt^^, defaultName, reply, 0, Point(-1), nil, GetMySFDialogFilter, nil, nil, nil);
  425.  
  426. { unlock the string resource }
  427.         HUnlock(Handle(hPrompt));
  428.  
  429. { if the user okayed the dialog, save the window to the specified file }
  430.         if (reply.sfGood) then
  431.             DoSaveAs := SaveWindow(@reply.sfFile, window)
  432.         else
  433.             DoSaveAs := userCanceledErr;
  434.  
  435.     end;  { DoSaveAs }
  436.  
  437.     function DoSave (window: WindowPtr): OSErr;
  438.         var
  439.             spec: FSSpec;
  440.             suggestedTarget: FSSpecPtr;
  441.             promptForNewFile, aliasTargetWasChanged: Boolean;
  442.     begin
  443.         suggestedTarget := nil;
  444.         promptForNewFile := true;
  445.  
  446. { resolve the alias associated with this window, if any }
  447.         if (DocumentPeek(window)^.fileAlias <> nil) then
  448.             if (ResolveAlias(nil, AliasHandle(DocumentPeek(window)^.fileAlias), spec, aliasTargetWasChanged) = noErr) then
  449.                 if (aliasTargetWasChanged) then
  450.                     suggestedTarget := @spec
  451.                 else
  452.                     promptForNewFile := false;
  453.  
  454. { if no file has been previously associated with this window, }
  455. { or if the alias resolution has failed, or if the alias target was changed, }
  456. { prompt the user for a new destination }
  457.         if (promptForNewFile) then
  458.             DoSave := DoSaveAs(suggestedTarget, window)
  459.         else
  460.             DoSave := SaveWindow(@spec, window);
  461.  
  462.     end;  { DoSave }
  463.  
  464.     function DoClose (closing: ClosingOption;
  465.                                     saving: SavingOption;
  466.                                     window: WindowPtr): OSErr;
  467.         const
  468.             kButtonSave = 1;
  469.             kButtonCancel = 2;
  470.             kButtonDontSave = 3;
  471.         var
  472.             s: Str255;
  473.             alertResult: Integer;
  474.             err: OSErr;
  475.     begin
  476.         DoClose := noErr;
  477.  
  478. { is this window dirty? }
  479.         if (WEGetModCount(DocumentPeek(window)^.hWE) > 0) then
  480.             begin
  481.  
  482. { do we have to ask the user whether to save changes? }
  483.                 if (saving = savingAsk) then
  484.                     begin
  485.  
  486. { prepare the parametric strings to be used in the Save Changes alert box }
  487.                         GetWTitle(window, s);
  488.                         ParamText(s, StringPtr(nil)^, StringPtr(nil)^, StringPtr(nil)^);
  489.                         GetIndString(s, kClosingQuittingStringsID, 1 + ORD(closing));
  490.                         ParamText(StringPtr(nil)^, s, StringPtr(nil)^, StringPtr(nil)^);
  491.  
  492. { put up the Save Changes? alert box }
  493. {$IFC NOT UNDEFINED THINK_PASCAL}
  494.                         SetCursor(arrow);
  495. {$ELSEC}
  496.                         SetCursor(qd.arrow);
  497. {$ENDC}
  498.                         alertResult := Alert(kAlertSaveChanges, GetMyStandardDialogFilter);
  499.  
  500. { exit if the user canceled the alert box }
  501.                         if (alertResult = kButtonCancel) then
  502.                             begin
  503.                                 DoClose := userCanceledErr;
  504.                                 Exit(DoClose);
  505.                             end;
  506.  
  507.                         if (alertResult = kButtonSave) then
  508.                             saving := savingYes
  509.                         else
  510.                             saving := savingNo;
  511.                     end;  { if saving = savingAsk }
  512.  
  513.                 if (saving = savingYes) then
  514.                     begin
  515.                         err := DoSave(window);
  516.                         if (err <> noErr) then
  517.                             begin
  518.                                 DoClose := err;
  519.                                 Exit(DoClose);
  520.                             end;
  521.                     end;
  522.             end;  { if window is dirty }
  523.  
  524. { destroy the window }
  525.         DestroyWindow(window);
  526.  
  527.     end;  { DoClose }
  528.  
  529.     function DoQuit (saving: SavingOption): OSErr;
  530.         var
  531.             window: WindowPtr;
  532.             err: OSErr;
  533.     begin
  534.         DoQuit := noErr;
  535.  
  536. { close all open windows }
  537.         repeat
  538.             window := FrontWindow;
  539.             if (window <> nil) then
  540.                 begin
  541.                     err := DoClose(closingApplication, saving, window);
  542.                     if (err <> noErr) then
  543.                         begin
  544.                             DoQuit := err;
  545.                             Exit(DoQuit);
  546.                         end;
  547.                 end;
  548.         until (window = nil);
  549.  
  550. { set a flag so we drop out of the event loop }
  551.         gExiting := true;
  552.  
  553.     end;  { DoQuit }
  554.  
  555.     procedure DoAppleChoice (menuItem: Integer);
  556.     begin
  557.         if (menuItem = kItemAbout) then
  558.             DoAboutBox(kDialogAboutBox)
  559.         else
  560.             DoDeskAcc(menuItem);
  561.     end;  { DoAppleChoice }
  562.  
  563.     procedure DoFileChoice (menuItem: Integer);
  564.         var
  565.             window: WindowPtr;
  566.     begin
  567.         window := FrontWindow;
  568.  
  569.         case menuItem of
  570.  
  571.             kItemNew: 
  572.                 if (DoNew <> noErr) then
  573.                     ;
  574.  
  575.             kItemOpen: 
  576.                 if (DoOpen <> noErr) then
  577.                     ;
  578.  
  579.             kItemClose: 
  580.                 if (DoClose(closingWindow, savingAsk, window) <> noErr) then
  581.                     ;
  582.  
  583.             kItemSave: 
  584.                 if (DoSave(window) <> noErr) then
  585.                     ;
  586.  
  587.             kItemSaveAs: 
  588.                 if (DoSaveAs(nil, window) <> noErr) then
  589.                     ;
  590.  
  591.             kItemQuit: 
  592.                 if (DoQuit(savingAsk) <> noErr) then
  593.                     ;
  594.  
  595.             otherwise
  596.                 ;
  597.         end;  { case menuItem }
  598.     end;  { DoFileChoice }
  599.  
  600.     procedure DoEditChoice (menuItem: Integer);
  601.         var
  602.             window: WindowPtr;
  603.             hWE: WEHandle;
  604.     begin
  605.  
  606. { do nothing if no window is active }
  607.         window := FrontWindow;
  608.         if (window = nil) then
  609.             Exit(DoEditChoice);
  610.         hWE := DocumentPeek(window)^.hWE;
  611.  
  612.         case menuItem of
  613.  
  614.             kItemUndo: 
  615.                 if (WEUndo(hWE) <> noErr) then
  616.                     ;
  617.  
  618.             kItemCut: 
  619.                 if (WECut(hWE) <> noErr) then
  620.                     ;
  621.  
  622.             kItemCopy: 
  623.                 if (WECopy(hWE) <> noErr) then
  624.                     ;
  625.  
  626.             kItemPaste: 
  627.                 if (WEPaste(hWE) <> noErr) then
  628.                     ;
  629.  
  630.             kItemClear: 
  631.                 if (WEDelete(hWE) <> noErr) then
  632.                     ;
  633.  
  634.             kItemSelectAll: 
  635.                 WESetSelection(0, maxLongInt, hWE);
  636.  
  637.             otherwise
  638.                 ;
  639.         end;  { case }
  640.     end;  { DoEditChoice }
  641.  
  642.     procedure DoFontChoice (menuItem: Integer);
  643.         var
  644.             window: WindowPtr;
  645.             fontName: Str255;
  646.             ts: TextStyle;
  647.     begin
  648.         window := FrontWindow;
  649.         if (window <> nil) then
  650.             begin
  651.                 GetMenuItemText(GetMenuHandle(kMenuFont), menuItem, fontName);
  652.                 GetFNum(fontName, ts.tsFont);
  653.                 if (WESetStyle(weDoFont, ts, DocumentPeek(window)^.hWE) <> noErr) then
  654.                     ;
  655.             end;
  656.     end;  { DoFontChoice }
  657.  
  658.     procedure DoSizeChoice (menuItem: Integer);
  659.         var
  660.             window: WindowPtr;
  661.             sizeString: Str255;
  662.             longSize: LongInt;
  663.             mode: Integer;
  664.             ts: TextStyle;
  665.     begin
  666.         window := FrontWindow;
  667.         if (window <> nil) then
  668.             begin
  669.  
  670.                 if (menuItem <= kItemLastSize) then
  671.                     begin
  672.                         GetMenuItemText(GetMenuHandle(kMenuSize), menuItem, sizeString);
  673.                         StringToNum(sizeString, longSize);
  674.                         mode := weDoSize;
  675.                         ts.tsSize := longSize;
  676.                     end
  677.                 else if (menuItem = kItemSmaller) then
  678.                     begin
  679.                         mode := weDoAddSize;
  680.                         ts.tsSize := -1;
  681.                     end
  682.                 else if (menuItem = kItemLarger) then
  683.                     begin
  684.                         mode := weDoAddSize;
  685.                         ts.tsSize := +1;
  686.                     end;
  687.  
  688.                 if (WESetStyle(mode, ts, DocumentPeek(window)^.hWE) <> noErr) then
  689.                     ;
  690.  
  691.             end;
  692.     end;  { DoSizeChoice }
  693.  
  694.     procedure DoStyleChoice (menuItem: Integer);
  695.         var
  696.             window: WindowPtr;
  697.             ts: TextStyle;
  698.     begin
  699.         window := FrontWindow;
  700.         if (window <> nil) then
  701.             begin
  702.  
  703.                 case menuItem of
  704.  
  705.                     kItemPlainText: 
  706.                         ts.tsFace := [];
  707.  
  708.                     kItemBold: 
  709.                         ts.tsFace := [bold];
  710.  
  711.                     kItemItalic: 
  712.                         ts.tsFace := [italic];
  713.  
  714.                     kItemUnderline: 
  715.                         ts.tsFace := [underline];
  716.  
  717.                     kItemOutline: 
  718.                         ts.tsFace := [outline];
  719.  
  720.                     kItemShadow: 
  721.                         ts.tsFace := [shadow];
  722.  
  723.                     kItemCondensed: 
  724.                         ts.tsFace := [condense];
  725.  
  726.                     kItemExtended: 
  727.                         ts.tsFace := [extend];
  728.  
  729.                     otherwise
  730.                         Exit(DoStyleChoice);
  731.                 end;  { case menuItem }
  732.  
  733.                 if (WESetStyle(weDoFace + weDoToggleFace, ts, DocumentPeek(window)^.hWE) <> noErr) then
  734.                     ;
  735.  
  736.             end;
  737.     end;  { DoStyleChoice }
  738.  
  739.     procedure DoColorChoice (menuItem: Integer);
  740.         var
  741.             window: WindowPtr;
  742.             i: Integer;
  743.             ts: TextStyle;
  744.     begin
  745.  
  746. { do nothing if there is no front window }
  747.         window := FrontWindow;
  748.         if (window = nil) then
  749.             Exit(DoColorChoice);
  750.  
  751. { find the color corresponding to the chosen menu item }
  752.         with MenuCRsrcHandle(sColors)^^ do
  753.             for i := numEntries - 1 downto 0 do
  754.                 if (mcEntryRecs[i].mctItem = menuItem) then
  755.                     begin
  756.                         ts.tsColor := mcEntryRecs[i].mctRGB2;
  757.                         if (WESetStyle(weDoColor, ts, DocumentPeek(window)^.hWE) <> noErr) then
  758.                             ;
  759.                     end;
  760.     end;  { DoColorChoice }
  761.  
  762.     procedure DoAlignChoice (menuItem: Integer);
  763.         var
  764.             window: WindowPtr;
  765.             alignment: SignedByte;
  766.     begin
  767.         window := FrontWindow;
  768.         if (window <> nil) then
  769.             begin
  770.  
  771.                 case menuItem of
  772.  
  773.                     kItemAlignDefault: 
  774.                         alignment := weFlushDefault;
  775.  
  776.                     kItemAlignLeft: 
  777.                         alignment := weFlushLeft;
  778.  
  779.                     kItemCenter: 
  780.                         alignment := weCenter;
  781.  
  782.                     kItemAlignRight: 
  783.                         alignment := weFlushRight;
  784.  
  785.                     kItemJustify: 
  786.                         alignment := weJustify;
  787.  
  788.                     otherwise
  789.                         Exit(DoAlignChoice);
  790.                 end;  { case }
  791.  
  792. { set the alignment mode (this automatically redraws the text) }
  793.                 WESetAlignment(alignment, DocumentPeek(window)^.hWE);
  794.  
  795.             end;
  796.     end;  { DoAlignChoice }
  797.  
  798.     procedure DoFeatureChoice (menuItem: Integer);
  799.         var
  800.             window: WindowPtr;
  801.             hWE: WEHandle;
  802.             feature, oldSetting: Integer;
  803.     begin
  804.         window := FrontWindow;
  805.         if (window = nil) then
  806.             Exit(DoFeatureChoice);
  807.         hWE := DocumentPeek(window)^.hWE;
  808.  
  809.         if (menuItem = kItemTabHooks) then
  810.             begin
  811.  
  812. { install or remove our custom tab hooks }
  813.                 if (WEIsTabHooks(hWE) = false) then
  814.                     begin
  815.  
  816. { left-align the text (the hooks only work with left-aligned text) }
  817.                         WESetAlignment(weFlushLeft, hWE);
  818.  
  819. { install tab hooks }
  820.                         if (WEInstallTabHooks(hWE) <> noErr) then
  821.                             ;
  822.  
  823.                     end
  824.                 else
  825.                     begin
  826.  
  827. { remove tab hooks }
  828.                         if (WERemoveTabHooks(hWE) <> noErr) then
  829.                             ;
  830.                     end;
  831.  
  832. { turn the cursor into a wristwatch }
  833.                 SetCursor(GetCursor(watchCursor)^^);
  834.  
  835. { recalculate line breaks and redraw the text }
  836.                 if (WECalText(hWE) <> noErr) then
  837.                     ;
  838.             end
  839.         else
  840.             begin
  841.                 case menuItem of
  842.  
  843.                     kItemAutoScroll: 
  844.                         feature := weFAutoScroll;
  845.  
  846.                     kItemOutlineHilite: 
  847.                         feature := weFOutlineHilite;
  848.  
  849.                     kItemReadOnly: 
  850.                         feature := weFReadOnly;
  851.  
  852.                     kItemIntCutAndPaste: 
  853.                         feature := weFIntCutAndPaste;
  854.  
  855.                     kItemDragAndDrop: 
  856.                         feature := weFDragAndDrop;
  857.  
  858.                     kItemOffscreenDrawing: 
  859.                         feature := weFDrawOffscreen;
  860.  
  861.                     otherwise
  862.                         ;
  863.                 end;  { case }
  864.  
  865. { toggle the specified feature }
  866.                 oldSetting := WEFeatureFlag(feature, weBitToggle, hWE);
  867.  
  868.             end;
  869.     end;  { DoFeatureChoice }
  870.  
  871.     procedure DoMenuChoice (menuChoice: LongInt);
  872.         var
  873.             menuID, menuItem: Integer;
  874.     begin
  875.  
  876. { extract menu ID and menu item from menuChoice }
  877.         menuID := HiWrd(menuChoice);
  878.         menuItem := LoWrd(menuChoice);
  879.  
  880. { dispatch on menuID }
  881.         case menuID of
  882.  
  883.             kMenuApple: 
  884.                 DoAppleChoice(menuItem);
  885.  
  886.             kMenuFile: 
  887.                 DoFileChoice(menuItem);
  888.  
  889.             kMenuEdit: 
  890.                 DoEditChoice(menuItem);
  891.  
  892.             kMenuFont: 
  893.                 DoFontChoice(menuItem);
  894.  
  895.             kMenuSize: 
  896.                 DoSizeChoice(menuItem);
  897.  
  898.             kMenuStyle: 
  899.                 DoStyleChoice(menuItem);
  900.  
  901.             kMenuColor: 
  902.                 DoColorChoice(menuItem);
  903.  
  904.             kMenuFeatures: 
  905.                 DoFeatureChoice(menuItem);
  906.  
  907.             kMenuAlignment: 
  908.                 DoAlignChoice(menuItem);
  909.  
  910.             otherwise
  911.                 ;
  912.         end;  { case menuID }
  913.  
  914.         HiliteMenu(0);
  915.  
  916.     end;  { DoMenuChoice }
  917.  
  918. {$S Init}
  919.  
  920.     function InitializeMenus: OSErr;
  921.         var
  922.             err: OSErr;
  923.     begin
  924.         InitializeMenus := noErr;
  925.  
  926. { build up the whole menu bar from the 'MBAR' resource }
  927.         SetMenuBar(GetNewMBar(kMenuBarID));
  928.  
  929. { add names to the Apple and Font menus }
  930.         AppendResMenu(GetMenuHandle(kMenuApple), kTypeDeskAccessory);
  931.         AppendResMenu(GetMenuHandle(kMenuFont), kTypeFont);
  932.  
  933. { insert the Alignment submenu into the hierarchical portion of the menu list }
  934.         InsertMenu(GetMenu(kMenuAlignment), -1);
  935.  
  936. { disable the "Drag and Drop Editing" item in the Features menu once and for all }
  937. { if the Drag Manager isn't available }
  938.         if (gHasDragAndDrop = false) then
  939.             DisableItem(GetMenuHandle(kMenuFeatures), kItemDragAndDrop);
  940.  
  941. { load the menu color table for the Color menu }
  942.         sColors := GetResource(kTypeMenuColorTable, kMenuColor);
  943.         err := ResError;
  944.         if (err <> noErr) then
  945.             begin
  946.                 InitializeMenus := err;
  947.                 Exit(InitializeMenus);
  948.             end;
  949.         HNoPurge(sColors);
  950.  
  951. { draw the menu bar }
  952.         DrawMenuBar;
  953.  
  954.     end;  { InitializeMenus }
  955.  
  956. end.